package com.dd.cloud.user.service.doctor.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.UserConstants;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.utils.Assert;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.vo.PageVo;
import com.dd.cloud.user.entity.doctor.BindReviewPresDoctor;
import com.dd.cloud.user.entity.doctor.DoctorUser;
import com.dd.cloud.user.mapper.doctor.BindReviewPresDoctorMapper;
import com.dd.cloud.user.req.doctor.*;
import com.dd.cloud.user.res.doctor.BindReviewPresDoctorApplyPageRes;
import com.dd.cloud.user.res.doctor.BindReviewPresDoctorListRes;
import com.dd.cloud.user.res.doctor.BindReviewPresPageRes;
import com.dd.cloud.user.service.doctor.IBindReviewPresDoctorService;
import com.dd.cloud.user.service.doctor.IDoctorUserService;
import com.dd.cloud.user.service.news.INewsInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author Lx
 * @version 1.0
 */
@Slf4j
@Service
public class BindReviewPresDoctorServiceImpl extends ServiceImpl<BindReviewPresDoctorMapper, BindReviewPresDoctor> implements IBindReviewPresDoctorService {
    @Autowired
    private IDoctorUserService doctorUserService;
    @Autowired
    private INewsInfoService newsInfoService;

    /**
     * 申请签约审核医生
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyBindReviewPresDoctor(BindReviewPresDoctorCreateReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        QueryWrapper<BindReviewPresDoctor> qw = new QueryWrapper<>();
        qw.lambda().eq(BindReviewPresDoctor::getApplyDoctorId, loginInfo.getId());
        qw.lambda().in(BindReviewPresDoctor::getStatus, UserConstants.BindReviewPresDoctorStatus.NORMAL, UserConstants.BindReviewPresDoctorStatus.UN_REVIEW);
        int count = count(qw);
        if (count > 0) {
            throw new ZekeException(400, "您发起的签约请求待医生审核中，请勿重新申请");
        }
        BindReviewPresDoctor bindReviewPresDoctor = new BindReviewPresDoctor();
        BeanUtils.copyProperties(req, bindReviewPresDoctor);
        bindReviewPresDoctor.setApplyDoctorId(loginInfo.getId());
        bindReviewPresDoctor.setStatus(UserConstants.BindReviewPresDoctorStatus.UN_REVIEW);
        bindReviewPresDoctor.setCreateDate(LocalDateTime.now());
        save(bindReviewPresDoctor);
        newsInfoService.sendApplyDoctorBindHandleNotice(req.getReviewDoctorId());
    }

    /**
     * 无处方权医生 解约审核医生
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rescindBindReviewPresDoctor(BindReviewPresDoctorRescindReq req) {
        BindReviewPresDoctor bindReviewPresDoctor = getById(req.getId());
        if (bindReviewPresDoctor.getStatus() != UserConstants.BindReviewPresDoctorStatus.NORMAL) {
            throw new ZekeException(400, "该审核医生未在正常绑定状态,无法解约");
        }
        BindReviewPresDoctor update = new BindReviewPresDoctor();
        update.setId(req.getId());
        update.setStatus(UserConstants.BindReviewPresDoctorStatus.RESCIND);
        update.setRescindReason(req.getRescindReason());
        update.setUpdateDate(LocalDateTime.now());
        updateById(update);
    }

    /**
     * 无处方权医生 查询处方审核医生列表
     *
     * @return
     */
    @Override
    public List<BindReviewPresDoctorListRes> queryBindReviewPresDoctorList() {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        BindReviewPresDoctorListReq req = new BindReviewPresDoctorListReq();
        req.setApplyDoctorId(loginInfo.getId());
        req.setStatus(UserConstants.BindReviewPresDoctorStatus.DOCTOR_CLI_CAN1);
        List<BindReviewPresDoctorListRes> list1 = getBaseMapper().queryBindReviewPresDoctorList(req);
        req.setStatus(null);
        req.setLimit(1);
        List<BindReviewPresDoctorListRes> list2 = getBaseMapper().queryBindReviewPresDoctorList(req);
        if (!list2.isEmpty()) {
            BindReviewPresDoctorListRes res = list2.get(0);
            if (res.getStatus() == UserConstants.BindReviewPresDoctorStatus.REJECT || res.getStatus() == UserConstants.BindReviewPresDoctorStatus.UN_REVIEW) {
                return list2;
            }
        }
        return list1;
    }

    /**
     * 无处方权医生 查询可正常审方医生数量 用于开方判断是否能继续开方
     *
     * @param docId
     * @return
     */
    @Override
    public Integer queryBindReviewPresDoctorNormalCount(Integer docId) {
        if (docId == null) {
            LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
            docId = loginInfo.getId();
        }
        QueryWrapper<BindReviewPresDoctor> qw = new QueryWrapper<>();
        qw.lambda().eq(BindReviewPresDoctor::getApplyDoctorId, docId);
        qw.lambda().eq(BindReviewPresDoctor::getStatus, UserConstants.BindReviewPresDoctorStatus.NORMAL);
        return count(qw);
    }

    /**
     * 查询审核处方单列表
     *
     * @param req
     * @return
     */
    @Override
    public PageVo<BindReviewPresPageRes> queryBindReviewPresPage(BindReviewPresPageReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        if (req.getIsPresPower() == null) {
            Integer isPresPower = doctorUserService.getDoctorUserPresPower(loginInfo.getId());
            req.setIsPresPower(isPresPower);
        }
        if (req.getIsPresPower() == 0) {
            req.setApplyDoctorId(loginInfo.getId());
            if (req.getReviewDoctorId() == null) {
                throw new ZekeException(400, "审方医生id不能为空");
            }
        } else {
            req.setReviewDoctorId(loginInfo.getId());
        }
        if (req.getMergeStatus() == 1) {
            if (req.getIsPresPower() == 0) {
                req.setStatus("12,14");
            } else {
                req.setStatus("12");
            }
        } else {
            req.setStatus("1,13");
        }
        PageVo<BindReviewPresPageRes> pageVo = req.pageVoPojo();
        pageVo = getBaseMapper().queryBindReviewPresPage(pageVo, req);
        for (BindReviewPresPageRes item : pageVo.getRecords()) {
            if (item.getApplyDate() == null) {
                item.setApplyDate(item.getCreateDate());
            }
        }
        pageVo.setExtend(getBaseMapper().queryBindReviewPresExtend(req));
        return pageVo;
    }

    /**
     * 查询审核处方数量
     *
     * @param req
     * @return
     */
    @Override
    public BindReviewPresPageRes.BindReviewPresExtendRes queryBindReviewPresExtend(BindReviewPresPageReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        if (req.getIsPresPower() == null) {
            Integer isPresPower = doctorUserService.getDoctorUserPresPower(loginInfo.getId());
            req.setIsPresPower(isPresPower);
        }
        if (req.getIsPresPower() == 0) {
            req.setApplyDoctorId(loginInfo.getId());
            if (req.getReviewDoctorId() == null) {
                throw new ZekeException(400, "审方医生id不能为空");
            }
        } else {
            req.setReviewDoctorId(loginInfo.getId());
        }
        return getBaseMapper().queryBindReviewPresExtend(req);
    }

    /**
     * 有处方权医生 查询无处方权医生申请记录
     *
     * @param req
     * @return
     */
    @Override
    public PageVo<BindReviewPresDoctorApplyPageRes> queryBindReviewPresDoctorApplyPage(BindReviewPresDoctorApplyPageReq req) {
        Assert.verifyStatusIdsParam(req.getClass(), req);
        if (req.getReviewDoctorId() == null) {
            LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
            req.setReviewDoctorId(loginInfo.getId());
        }
        PageVo<BindReviewPresDoctorApplyPageRes> pageVo = req.pageVoPojo();
        pageVo = getBaseMapper().queryBindReviewPresDoctorApplyPage(pageVo, req);
        pageVo.setExtend(getBaseMapper().queryBindReviewPresDoctorApplyExtend(req));
        return pageVo;
    }

    /**
     * 有处方权医生审核无处方权医生申请记录
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bindReviewPresDoctorReview(BindReviewPresDoctorReviewReq req) {
        if (req.getStatus() != UserConstants.BindReviewPresDoctorStatus.NORMAL && req.getStatus() != UserConstants.BindReviewPresDoctorStatus.REJECT) {
            throw new ZekeException(400, "错误的审核状态");
        }
        BindReviewPresDoctor bindReviewPresDoctor = getById(req.getId());
        if (bindReviewPresDoctor.getStatus() != UserConstants.BindReviewPresDoctorStatus.UN_REVIEW) {
            throw new ZekeException(400, "该记录未在待审核中");
        }
        BindReviewPresDoctor update = new BindReviewPresDoctor();
        update.setId(req.getId());
        update.setStatus(req.getStatus());
        if (req.getStatus() == UserConstants.BindReviewPresDoctorStatus.REJECT) {
            update.setRejectReason(req.getRejectReason());
            update.setRejectDate(LocalDateTime.now());
        }
        update.setUpdateDate(LocalDateTime.now());
        updateById(update);
        newsInfoService.sendApplyDoctorBindReviewNotice(bindReviewPresDoctor.getApplyDoctorId(), req.getStatus() == UserConstants.BindReviewPresDoctorStatus.NORMAL ? 1 : 2);
    }

    /**
     * 有处方权医生 查询无处方权医生待审核数量
     *
     * @return
     */
    @Override
    public Integer queryBindReviewPresDoctorApplyNoReviewCount() {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.DOCTOR).get();
        QueryWrapper<BindReviewPresDoctor> qw = new QueryWrapper<>();
        qw.lambda().eq(BindReviewPresDoctor::getReviewDoctorId, loginInfo.getId());
        qw.lambda().eq(BindReviewPresDoctor::getStatus, UserConstants.BindReviewPresDoctorStatus.UN_REVIEW);
        return count(qw);
    }

    /**
     * 获取审核医生id
     *
     * @param docId
     * @return 正常返回审核医生id 错误返回-1
     */
    @Override
    public Integer[] queryReviewDoctorId(Integer docId) {
        DoctorUser doctorUser = doctorUserService.getById(docId);
        if (doctorUser == null) {
            throw new ZekeException(400, "医生信息不存在");
        }
        if (doctorUser.getIsPresPower() == 1) {
            return new Integer[]{doctorUser.getIsPresPower(), docId};
        } else {
            QueryWrapper<BindReviewPresDoctor> qw = new QueryWrapper<>();
            qw.lambda().eq(BindReviewPresDoctor::getApplyDoctorId, docId);
            qw.lambda().eq(BindReviewPresDoctor::getStatus, UserConstants.BindReviewPresDoctorStatus.NORMAL);
            BindReviewPresDoctor bindReviewPresDoctor = getOne(qw);
            if (bindReviewPresDoctor != null) {
                return new Integer[]{doctorUser.getIsPresPower(), bindReviewPresDoctor.getReviewDoctorId()};
            } else {
                qw.clear();
                qw.lambda().eq(BindReviewPresDoctor::getApplyDoctorId, docId);
                qw.lambda().eq(BindReviewPresDoctor::getStatus, UserConstants.BindReviewPresDoctorStatus.UN_REVIEW);
                int count = count(qw);
                if (count > 0) {
                    return new Integer[]{doctorUser.getIsPresPower(), -2};
                }
            }
        }
        return new Integer[]{doctorUser.getIsPresPower(), -1};
    }

    @Override
    public Integer queryReviewDoctorRes() {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        Integer doctorId = loginInfo.getId();
        LambdaQueryWrapper<BindReviewPresDoctor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BindReviewPresDoctor::getApplyDoctorId, doctorId)
                .eq(BindReviewPresDoctor::getStatus, 1)
                .last("limit 1");
        BindReviewPresDoctor presDoctor = this.getOne(queryWrapper);
        return presDoctor.getReviewDoctorId();
    }
}
